package org.smartercontext.contextmger.ciphermodule;

import java.math.BigInteger;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

/**
 * @author Juan Manuel Madrid Molina
 * @adapted_by Juan Pablo Cortes
 * @version 1.0
 * @creation_date 09 Mar 2014
 * @note This class is for free use. Juan Manuel uploaded it in moodle for her 
 * class (Seguridad)
 * This class allows encrypt and decrypt values based in
 * a key of 128 bytes
 * @limitation Because the key used is of 128-bit, the maximum string length to process
 * is 16
 */
public class CipherAES {

	public String encrypt_decrypt(String text, boolean type){
		byte []theKey = hexToBytes("2b7e151628aed2a6abf7158809cf4f3c");
		byte []theMsg = hexToBytes(text);
		
		String retorno="";
		
		try{
		
		SecretKey sk=new SecretKeySpec(theKey, "AES");
        Cipher cf=Cipher.getInstance("AES/ECB/NoPadding");
        
        if(type){  
        	cf.init(javax.crypto.Cipher.ENCRYPT_MODE, sk);
        }else{
        	cf.init(javax.crypto.Cipher.DECRYPT_MODE, sk);
        }
        
        byte[] theCph = cf.doFinal(theMsg);
//        System.out.println("Key     : "+bytesToHex(theKey));
//        System.out.println("Message : "+bytesToHex(theMsg));
//        System.out.println("Cipher  : "+bytesToHex(theCph));
        
        retorno=bytesToHex(theCph);
        
		}catch (Exception e) {
			System.out.println("Error de cifrado");
		}
        
		return retorno;
	}
	
	
	private byte[] hexToBytes(String str) {
		if (str == null) {
			return null;
		} else if (str.length() < 2) {
			return null;
		} else {
			int len = str.length() / 2;
			byte[] buffer = new byte[len];
			for (int i = 0; i < len; i++) {
				buffer[i] = (byte) Integer.parseInt(
						str.substring(i * 2, i * 2 + 2), 16);
			}
			return buffer;
		}
	}
	
	private String bytesToHex(byte[]data){
		if (data == null) {
			return null;
		} else {
			int len = data.length;
			String str = "";
			for (int i = 0; i < len; i++) {
				if ((data[i] & 0xFF) < 16)
					str = str + "0"
							+ java.lang.Integer.toHexString(data[i] & 0xFF);
				else
					str = str + java.lang.Integer.toHexString(data[i] & 0xFF);
			}
			return str.toUpperCase();
		}
	}
	
	public String stringToHex(String text){
		return String.format("%032x", new BigInteger(1, text.getBytes()));
	}
	
	/**
	 * @author Luigi Mendoza
	 * @url http://stackoverflow.com/questions/12039341/hex-to-string-in-java-performance-is-too-slow
	 * @param hex
	 * @return
	 */
	public String hexToString(String hex){
		StringBuilder sb = new StringBuilder();
	    char[] hexData = hex.toCharArray();
	    for (int count = 0; count < hexData.length - 1; count += 2) {
	        int firstDigit = Character.digit(hexData[count], 16);
	        int lastDigit = Character.digit(hexData[count + 1], 16);
	        int decimal = firstDigit * 16 + lastDigit;

	        if(decimal!=0){
	        sb.append((char)decimal);
	        }
	    }
	    return sb.toString();
	}
}
